/**********************************************************************
 * Filename: CalendarDate.java
 * Created: 2012/04/30
 * @author Fernando Brito e Abreu
 **********************************************************************/
package pt.iscteiul.worldfootball.businesslayer;

import java.util.Set;
import java.util.HashSet;

import com.projectpoint.annotationnotfinished.NotFinished;

@NotFinished(value = "Not tested")
public class CalendarDate {
	public static Set<CalendarDate> allInstances = new HashSet<CalendarDate>();

	private int day;
	private int month;
	private int year;

	/**********************************************************************
	 * Default constructor
	 **********************************************************************/
	public CalendarDate() {
		allInstances.add(this);
	}

	/**********************************************************************
	 * Parameterized constructor
	 * 
	 * @param day
	 *            the day to initialize
	 * @param month
	 *            the month to initialize
	 * @param year
	 *            the year to initialize
	 **********************************************************************/
	public CalendarDate(int day, int month, int year) {
		this.day = day;
		this.month = month;
		this.year = year;
		allInstances.add(this);
	}

	/**********************************************************************
	 * Standard attribute getter
	 * 
	 * @return the day of the calendarDate
	 **********************************************************************/
	public int day() {
		return day;
	}
	
	/**********************************************************************
	 * Standard attribute setter
	 * 
	 * @param day
	 *            the day to set
	 **********************************************************************/
	public void setDay(int day) {
		this.day = day;
	}
	
	/**********************************************************************
	 * Standard attribute getter
	 * 
	 * @return the month of the calendarDate
	 **********************************************************************/
	public int month() {
		return month;
	}

	/**********************************************************************
	 * Standard attribute setter
	 * 
	 * @param month
	 *            the month to set
	 **********************************************************************/
	public void setMonth(int month) {
		this.month = month;
	}

	/**********************************************************************
	 * Standard attribute getter
	 * 
	 * @return the year of the calendarDate
	 **********************************************************************/
	public int year() {
		return year;
	}

	/**********************************************************************
	 * Standard attribute setter
	 * 
	 * @param year
	 *            the year to set
	 **********************************************************************/
	public void setYear(int year) {
		this.year = year;
	}

	/**********************************************************************
	 * User-defined operation specified in SOIL/OCL
	 * 
	 * @param day
	 *            the day to set
	 * @param month
	 *            the month to set
	 * @param year
	 *            the year to set
	 **********************************************************************/
	public void init(int day, int month, int year) {
		// TODO
		// self.day := day;
		// self.month := month;
		// self.year := year;
		this.day = day;
		this.month = month;
		this.year = year;
	}

	/**********************************************************************
	 * User-defined operation specified in SOIL/OCL
	 * 
	 * @param date
	 *            the date to set
	 **********************************************************************/
	public void initS(String date) {
		// TODO
		// self.year := date.substring(1,4).toInteger;
		// self.month := date.substring(6,7).toInteger;
		// self.day := date.substring(9,10).toInteger;
		this.year = Integer.parseInt(date.substring(0, 4));
		this.month = Integer.parseInt(date.substring(5, 7));
		this.day = Integer.parseInt(date.substring(8, 10));
	}

	/**********************************************************************
	 * User-defined operation specified in SOIL/OCL
	 * 
	 * @param t
	 *            the t to set
	 **********************************************************************/
	public boolean isAfter(CalendarDate t) {
		// TODO
		// return if (self.year = t.year) then if (self.month = t.month) then
		// (self.day > t.day) else (self.month > t.month) endif else (self.year
		// > t.year) endif
		if (this.year == t.year) {
			if (this.month == t.month) {
				return this.day > t.day;
			}
			return this.month > t.month;
		}
		return this.year > t.year;
	}

	/**********************************************************************
	 * User-defined operation specified in SOIL/OCL
	 * 
	 * @param t
	 *            the t to set
	 **********************************************************************/
	public boolean isBefore(CalendarDate t) {
		// TODO
		// return if (self.year = t.year) then if (self.month = t.month) then
		// (self.day < t.day) else (self.month < t.month) endif else (self.year
		// < t.year) endif
		if (this.year == t.year) {
			if (this.month == t.month) {
				return this.day < t.day;
			}
			return this.month < t.month;
		}
		return this.year < t.year;
	}

	/**********************************************************************
	 * User-defined operation specified in SOIL/OCL
	 * 
	 * @param x
	 *            the x to set
	 * @param y
	 *            the y to set
	 **********************************************************************/
	public boolean isDivisible(int x, int y) {
		// TODO
		// return (((x div y) * y) = x)
		return ((double) x % (double) y) == 0;
	}

	/**********************************************************************
	 * User-defined operation specified in SOIL/OCL
	 * 
	 * @param t
	 *            the t to set
	 **********************************************************************/
	public boolean isEqual(CalendarDate t) {
		// TODO
		// return (((self.year = t.year) and (self.month = t.month)) and
		// (self.day = t.day))

		return (((this.year == t.year) && (this.month == t.month)) && (this.day == t.day));
	}

	/**********************************************************************
	 * User-defined operation specified in SOIL/OCL
	 **********************************************************************/
	public boolean isLeap() {
		// TODO
		// return if (self.isDivisible(self.year, 400) or
		// self.isDivisible(self.year, 4)) then true else if
		// self.isDivisible(self.year, 100) then false else if
		// self.isDivisible(self.year, 4) then true else false endif endif endif
		if (isDivisible(this.year, 400) || isDivisible(this.year, 4)) {
			return true;
		}
		else if (isDivisible(this.year, 100)) {
			return false;
		} 
		else
			return false;

	}

	/**********************************************************************
	 * User-defined operation specified in SOIL/OCL
	 * 
	 * @param date
	 *            the date to set
	 **********************************************************************/
	public CalendarDate stringToDate(String date) {
		// TODO
		// date_year := date.substring(1,4);
		int date_year = Integer.parseInt(date.substring(0, 4));
		// date_month := date.substring(6,7);
		int date_month = Integer.parseInt(date.substring(5, 7));
		// date_day := date.substring(9,10);
		int date_day = Integer.parseInt(date.substring(8, 10));
		// result := CalendarDate.allInstances->select(cd : CalendarDate |
		// (((cd.year = date_year.toInteger) and (cd.month =
		// date_month.toInteger)) and (cd.day =
		// date_day.toInteger)))->asSequence->first;
		CalendarDate result = null;
		for (CalendarDate cd : CalendarDate.allInstances) {
			if (cd.year() == date_year && cd.month() == date_month
					&& cd.day() == date_day) {
				result = cd;
				break;
			}
		}
		// if result.isUndefined then result := new CalendarDate(((('D' +
		// date_year) + date_month) + date_day));
		if (result == null) {
			result = new CalendarDate(date_day, date_month, date_year);
		}
		// result.initS(date) end;
		result.initS(date);

		return result;

	}

	/**********************************************************************
	 * User-defined operation specified in SOIL/OCL
	 * 
	 * @param t
	 *            the t to set
	 **********************************************************************/
	public int yearsSince(CalendarDate t) {
		// TODO
		// return if ((self.month < t.month) or ((self.month = t.month) and
		// (self.day < t.day))) then ((self.year - t.year) - 1) else (self.year
		// - t.year) endif
		if (this.month < t.month || (this.month == t.month && this.day < t.day)) {
			return this.year - t.year - 1;
		}
		return this.year - t.year;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	/**********************************************************************
	 * Object serializer
	 **********************************************************************/
	public String toString() {
		return "CalendarDate [day=" + day + ", month=" + month + ", year="
				+ year + "]\n";
	}

}
